package com.zzz.thrift.gateway.service;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.server.TThreadedSelectorServer;
import org.apache.thrift.transport.*;
import org.apache.thrift.transport.layered.TFastFramedTransport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class ThirftGatewayProxy implements CommandLineRunner {

    private static final String REGISTER_EUREKA = "eureka";
    private static final String REGISTER_NACOS = "nacos";

    // 是否开启thrift服务
    @Value("${thrift.service.enable:false}")
    private boolean thriftServiceEnable;
    // thrift服务注册中心
    @Value("${thrift.service.register:}")
    private String thriftServiceRegister;
    // 是否开启thrift简单模式端口
    @Value("${thrift.service.simple.enable:false}")
    private boolean simpleThriftServiceEnable;
    // thrift简单模式端口
    @Value("${thrift.service.simple.port:0}")
    private int simpleThriftServicePort;
    // 是否开启thrift加密模式端口
    @Value("${thrift.service.secure.enable:false}")
    private boolean secureThriftServiceEnable;
    // thrift加密模式端口
    @Value("${thrift.service.secure.port:0}")
    private int secureThriftServicePort;
    // thrift加密模式超时时间
    @Value("${thrift.service.secure.timeout:10000}")
    private int secureThriftServiceTimeout;
    @Value("${thrift.service.secure.password:}")
    private String secureThriftServicePwd;


    @Autowired
    private ThriftProxyEurekaProcessor proxyEurekaProcessor;
    @Autowired
    private ThriftProxyNacosProcessor proxyNacosProcessor;

    @Override
    public void run(String... args) throws Exception {
        if(thriftServiceEnable) {
            if(REGISTER_EUREKA.equals(thriftServiceRegister)) {
                thriftProxyInit(proxyEurekaProcessor);
            } else if(REGISTER_NACOS.equals(thriftServiceRegister)) {
                thriftProxyInit(proxyNacosProcessor);
            }
        }
    }

    private void thriftProxyInit(TProcessor tProcessor) throws Exception {
        // 简单模式
        if(simpleThriftServiceEnable) {
            SimpleThriftProxy simpleThriftProxy = new SimpleThriftProxy(tProcessor);
            new Thread(simpleThriftProxy).start();
        }
        // 加密模式
        if(secureThriftServiceEnable) {
            SecureThriftProxy secureThriftProxy = new SecureThriftProxy(tProcessor);
            new Thread(secureThriftProxy).start();
        }
    }

    class SimpleThriftProxy implements Runnable {
        private TProcessor processor;

        public SimpleThriftProxy(TProcessor processor) {
            this.processor = processor;
        }
        @SneakyThrows
        @Override
        public void run() {
            simple(processor);
        }
    }

    class SecureThriftProxy implements Runnable {
        private TProcessor processor;

        public SecureThriftProxy(TProcessor processor) {
            this.processor = processor;
        }
        @SneakyThrows
        @Override
        public void run() {
            secure(processor);
        }
    }

    /**
     *  普通模式
     * @param tProcessor
     * @throws Exception
     */
    private void simple(TProcessor tProcessor) throws Exception {
        TNonblockingServerSocket tNonblockingServerSocket = new TNonblockingServerSocket(new TNonblockingServerSocket.NonblockingAbstractServerSocketArgs().port(simpleThriftServicePort));
        TThreadedSelectorServer.Args args = new TThreadedSelectorServer.Args(tNonblockingServerSocket);
        args.processor(tProcessor);
        //指定的通信协议
        args.protocolFactory(new TBinaryProtocol.Factory());
        //指定的通信方式
        args.transportFactory(new TFastFramedTransport.Factory());
        //指定的服务器模式
        TServer server = new TThreadedSelectorServer(args);
        log.info("Starting the simple proxy on " + simpleThriftServicePort + "...");
        server.serve();
    }

    /**
     *  安全模式
     * @param tProcessor
     * @throws Exception
     */
    private void secure(TProcessor tProcessor) throws Exception {
        String keyStore = this.getClass().getResource("/key/mykeystore.jks").getPath();
        TSSLTransportFactory.TSSLTransportParameters params = new TSSLTransportFactory.TSSLTransportParameters();
        params.setKeyStore(keyStore, secureThriftServicePwd);
        TServerTransport serverTransport = TSSLTransportFactory.getServerSocket(secureThriftServicePort, secureThriftServiceTimeout, null, params);

        TThreadPoolServer.Args args = new TThreadPoolServer.Args(serverTransport);
        args.processor(tProcessor);
        //指定的通信协议
        args.protocolFactory(new TBinaryProtocol.Factory());
        //指定的通信方式
        args.transportFactory(new TFastFramedTransport.Factory());
        //指定的服务器模式
        TServer server = new TThreadPoolServer(args);
        log.info("Starting the simple proxy on " + secureThriftServicePort + "...");
        server.serve();
    }




}
